﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.Diagnostics;

namespace ImageRecognition2.MouseImageTools
{
    /// <summary>
    /// Used by the selection tool to create a selection.
    /// On mouse up a union rectangle is created
    /// all controls contained in that rectangle go there.
    /// </summary>    
    [Serializable]
    public class Selector : MouseImageToolBase
    {
        #region Declarations
        private bool m_bFilledRectangleMode = false;
        private Rectangle m_Rectangle = Rectangle.Empty;
        private bool m_bHaveMouse = false;
        private Point ptOriginal = Point.Empty;
        private Point ptLast = Point.Empty;
        private Control m_View = null;
        private int m_nOpacity = 0;

        private Color m_Color = Color.FromArgb(50, 255, 255, 255);
        private FrameStyle M_FRAMESTYLE = FrameStyle.Thick;
        #endregion Declarations

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="CSelector"/> class.
        /// </summary>
        /// <param name="_view">The _view.</param>
        public Selector(Control _view)
            : base(_view)
        {
            this.m_View = _view;
            if (_view == null)
            {
            }
            this.m_bHaveMouse = false;
        }
        #endregion Constructors

        #region Properties
        /// <summary>
        /// only true if selection has captured mouse, i.e. actually dragging a rectangle on the screen...
        /// </summary>
        public bool HaveMouse
        {
            get { return this.m_bHaveMouse; }
        }

        public Control View
        {
            get { return this.m_View; }
            set { this.m_View = value; }
        }

        public int Opacity
        {
            get { return m_nOpacity; }
            set { m_nOpacity = value; }
        }

        /// <summary>
        /// Color of the Selection
        /// </summary>
        public Color Color
        {
            get { return this.m_Color; }
            set { this.m_Color = Color.FromArgb(Opacity, value.R, value.G, value.B); }
        }

        /// <summary>
        /// Gets or sets the rectangle.
        /// </summary>
        /// <value>The rectangle.</value>
        public Rectangle Rectangle
        {
            get { return this.m_Rectangle; }
            set { this.m_Rectangle = value; }
        }

        /// <summary>
        /// determines look of selection, straight line, or dashed dots
        /// </summary>
        public FrameStyle FrameStyle
        {
            get { return this.M_FRAMESTYLE; }
            set { this.M_FRAMESTYLE = value; }
        }

        public bool FillRectangleMode
        {
            get { return m_bFilledRectangleMode; }
            set { m_bFilledRectangleMode = value; }
        }

        #endregion Properties

        #region Methods
        /// <summary>
        /// Draws the reversible rectangle.
        /// </summary>
        /// <param name="p1">The p1.</param>
        /// <param name="p2">The p2.</param>
        /// <returns></returns>
        private Rectangle CalcRectangle(Point p1, Point p2, bool _bConvertToScreen)
        {
            Rectangle rc = new Rectangle();
            if (_bConvertToScreen)
            {
                p1 = this.m_View.PointToScreen(p1);
                p2 = this.m_View.PointToScreen(p2);
            }
            if (p1.X < p2.X)
            {
                rc.X = p1.X;
                rc.Width = p2.X - p1.X;
            }
            else
            {
                rc.X = p2.X;
                rc.Width = p1.X - p2.X;
            }
            if (p1.Y < p2.Y)
            {
                rc.Y = p1.Y;
                rc.Height = p2.Y - p1.Y;
            }
            else
            {
                rc.Y = p2.Y;
                rc.Height = p1.Y - p2.Y;
            }

            return rc;
        }
        #endregion Methods

        #region Events

        public override void OnPaint(object sender, PaintEventArgs e)
        {
            Rectangle rect = CalcRectangle(ptOriginal, ptLast, false);
            if (m_bFilledRectangleMode)
            {
                e.Graphics.FillRectangle(new SolidBrush(m_Color), rect);
            }
            else
            {
                e.Graphics.DrawRectangle(new Pen(m_Color, 7), rect);
            }
        }
        /// <summary>
        /// Called when [mouse down].
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.MouseEventArgs"/> instance containing the event data.</param>
        public override void OnMouseDown(object sender, MouseEventArgs e)
        {
            m_bHaveMouse = true;
            ptOriginal = new Point(e.X, e.Y);
            ptLast = ptOriginal;
        }

        /// <summary>
        /// Called when [mouse up].
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.MouseEventArgs"/> instance containing the event data.</param>
        public override void OnMouseUp(object sender, MouseEventArgs e)
        {
            m_bHaveMouse = false;
            if (ptLast.X != -1)
            {
                Point ptCurrent = new Point(e.X, e.Y);
                this.m_Rectangle = CalcRectangle(ptOriginal, ptLast, true);
                this.m_Rectangle = DrawReversibleRectangle(ptOriginal, ptLast,m_Color, FrameStyle.Thick);
            }
            this.SelectionFinished(sender, e);
            ptLast = new Point(-1, -1);
            ptOriginal = new Point(-1, -1);
        }

        /// <summary>
        /// Called when [mouse move].
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.MouseEventArgs"/> instance containing the event data.</param>
        public override void OnMouseMove(object sender, MouseEventArgs e)
        {
            Point ptCurrent = new Point(e.X, e.Y);
            if (this.m_bHaveMouse)
            {
                if (ptLast.X != -1)
                {
                    DrawReversibleRectangle(ptOriginal, ptLast, m_Color, FrameStyle.Thick);
                }
                ptLast = ptCurrent;
                DrawReversibleRectangle(ptOriginal, ptCurrent, m_Color, FrameStyle.Thick);
            }
        }
        #endregion Events

        /// <summary>
        /// if the Selection is finished...
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="evt">The <see cref="System.Windows.Forms.MouseEventArgs"/> instance containing the event data.</param>
        private void SelectionFinished(object sender, MouseEventArgs evt)
        {
            Point pt1 = this.m_View.PointToClient(m_Rectangle.Location);
            this.m_Rectangle = new Rectangle(pt1, m_Rectangle.Size);
            if (this.m_Rectangle.IsEmpty)
            {
                return;
            }
        }

        /// <summary>
        /// Disposes this instance
        /// </summary>
        public override void Dispose()
        {
            throw new Exception("The method or operation is not implemented.");
        }
    }
}
